package org.example.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.example.chain.AbstractChainContext;
import org.example.constant.MessageConstant;
import org.example.constant.UserMessageConstant;
import org.example.context.UserContext;
import org.example.dao.entity.UserRoles;
import org.example.dao.entity.Users;
import org.example.dao.mapper.UserMapper;
import org.example.dao.mapper.UserRolesMapper;
import org.example.dto.DetailDTO;
import org.example.dto.req.*;
import org.example.dto.resp.UserPageVO;
import org.example.dto.resp.UserVO;
import org.example.enums.UserChainMarkEnum;
import org.example.exception.*;
import org.example.feign.PermissionServiceFeignClient;
import org.example.mq.LogProduct;
import org.example.mq.OperationLogEvent;
import org.example.properties.JwtProperties;
import org.example.result.Result;
import org.example.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, Users> implements UserService {


    @Autowired
    private UserMapper userMapper;
    @Resource
    private UserRolesMapper userRolesMapper;
    @Resource
    private PermissionServiceFeignClient permissionServiceFeignClient;
    @Resource
    private LogProduct logProduct;

    @Autowired
    private JwtProperties jwtProperties;

    @Resource
    private AbstractChainContext<UserRegisterReqDTO> userRegisterAbstractChainContext;


    @Override
    public Result createUser(UserRegisterReqDTO reqDTO, HttpServletRequest request) {
        //        if (StringUtils.isEmpty(reqDTO.getUsername())) {
//            throw new UserNameNotNull("用户名不能为空");
//        }
//
//        if (StringUtils.isEmpty(reqDTO.getPassword())) {
//            throw new PasswordNotNull(MessageConstant.PASSWORD_NOT_NULL);
//        }
//
//        if (StringUtils.isEmpty(reqDTO.getEmail())) {
//            throw new EmailNotNull("邮箱不能为空");
//        }
//
//        if (StringUtils.isEmpty(reqDTO.getPhone())) {
//            throw new PhoneNotNull("手机号不能为空");
//        }
//
//        if (StringUtils.isNotEmpty(reqDTO.getPhone()) && !PHONE_PATTERN.matcher(reqDTO.getPhone()).matches()) {
//            throw new IllegalArgumentException("手机号格式不正确");
//        }
//
//        QueryWrapper<Users> qw = new QueryWrapper<>();
//        qw.eq("username", reqDTO.getUsername());
//        if (CollectionUtil.isNotEmpty(list(qw))) {
//            throw new IllegalArgumentException("用户名已存在");
//        }
//
//        QueryWrapper<Users> qw1 = new QueryWrapper<>();
//        qw1.eq("phone", reqDTO.getPhone());
//        if (CollectionUtil.isNotEmpty(list(qw1))) {
//            throw new IllegalArgumentException("注册手机号重复");
//        }
//
//        QueryWrapper<Users> qw2 = new QueryWrapper<>();
//        qw2.eq("email", reqDTO.getEmail());
//        if (CollectionUtil.isNotEmpty(list(qw2))) {
//            throw new IllegalArgumentException("注册邮箱重复");
//        }
        // 用户注册，责任链处理参数校验、重复性校验（已抽离）
        userRegisterAbstractChainContext.handler(UserChainMarkEnum.USER_REGISTER_FILTER.name(), reqDTO);

        // 构建用户实体
        Users user = Users.builder()
                .userName(reqDTO.getUserName())
                .password(reqDTO.getPassword())
                .email(reqDTO.getEmail())
                .phone(reqDTO.getPhone())
                .build();

        // 插入用户数据
        userMapper.insert(user);

        // 调用权限服务，绑定默认角色（RPC Feign 调用）
        Result result = permissionServiceFeignClient.bindDefaultRole(user.getUserId());

        // 判断绑定默认角色是否成功
        if (result.getCode() == 0 && result.getMsg().equals(MessageConstant.BIND_DEFAULT_ROLE_FAILED)) {
            return Result.error(MessageConstant.BIND_DEFAULT_ROLE_FAILED);
        }

        return Result.success(MessageConstant.REGISTER_SUCCESS);
    }

    @Override
    public Users login(UserLoginReqDTO reqDTO, HttpServletRequest request) {
        // 登录，校验账号密码
        Users users = userMapper.selectOne(new LambdaQueryWrapper<Users>()
                .eq(Users::getUserName, reqDTO.getUserName())
                .eq(Users::getPassword, reqDTO.getPassword()));

        // 如果查不到用户，抛出异常
        if (Objects.isNull(users)) {
            throw new AccountOrPasswordErrorException(MessageConstant.ACCOUNT_PASSWORD_ERROR);
        }

        return users;
    }

    @Override
    public UserPageVO pagequery(UserPageQueryReqDTO reqDTO, HttpServletRequest request) {
        // 防止前端传错分页参数，设置默认值
        Integer page = reqDTO.getPage() == null || reqDTO.getPage() <= 0 ? 1 : reqDTO.getPage();
        Integer pageSize = reqDTO.getPageSize() == null || reqDTO.getPageSize() <= 0 ? 10 : reqDTO.getPageSize();


//        //获取当前用户Id
//        //从请求头中获取token
//        String token = request.getHeader(jwtProperties.getUserTokenName());
//        //校验令牌
//        log.info("jwt校验:{}", token);
//        Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
//        Object userIdObj = claims.get(JwtClaimsConstant.USER_ID.toString());
//        BigInteger currentUserId = BigInteger.valueOf(Long.parseLong(userIdObj.toString()));
        // 获取当前登录用户ID(将用户信息存储到ThreadLocal里边方便调用)
        BigInteger userId = UserContext.getCurrentUserId();

        // 查询当前用户是否存在
        QueryWrapper<Users> qw = new QueryWrapper<>();
        qw.eq(UserMessageConstant.USER_ID, userId);
        Users users = userMapper.selectOne(qw);
        if (Objects.isNull(users)) {
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        // 调用权限服务获取用户角色
        String roleCode = permissionServiceFeignClient.getUserRoleCode(userId);
        if (Objects.isNull(roleCode)) {
            throw new NoPermissionException(MessageConstant.NO_PERMISSION);
        }

        QueryWrapper<Users> queryWrapper = new QueryWrapper<>();

        // 权限判断
        if (UserMessageConstant.USER.equals(roleCode)) {
            // 普通用户只能查询自己
            queryWrapper.eq(UserMessageConstant.USER_ID, userId);
        } else if (UserMessageConstant.ADMIN.equals(roleCode)) {
            // 管理员只能查询普通用户和自己
            List<BigInteger> userIds = userMapper.selectUserIdsByRoleCode(UserMessageConstant.USER);
            if (CollectionUtil.isEmpty(userIds)) {
                throw new NoRegularUserException(MessageConstant.NO_REGULAR_USER);
            }
            userIds.add(userId);
            queryWrapper.in(UserMessageConstant.USER_ID, userIds);
        } else if (UserMessageConstant.SUPER_ADMIN.equals(roleCode)) {
            // 超级管理员可以查询所有用户
        } else {
            throw new NoPermissionException(MessageConstant.NO_PERMISSION);
        }

        // 分页查询
        Page<Users> page1 = userMapper.selectPage(new Page<>(page, pageSize), queryWrapper);

        // 将分页结果转换成VO返回
        List<UserVO> userPageVOS = page1.getRecords().stream().map(users1 -> {
            UserVO userVO = new UserVO();
            userVO.setUserId(users1.getUserId());
            userVO.setUserName(users1.getUserName());
            userVO.setEmail(users1.getEmail());
            userVO.setPhone(users1.getPhone());
            return userVO;
        }).collect(Collectors.toList());

        // 构造分页结果对象
        UserPageVO userPageVO = new UserPageVO();
        userPageVO.setTotal(page1.getTotal());
        userPageVO.setRecords(userPageVOS);

        return userPageVO;
    }

    @Override
    public UserVO getUserInfoById(BigInteger targetUserId, HttpServletRequest request) {
        // 参数校验
        if (targetUserId == null) {
            throw new ParameterNotNullException(MessageConstant.USER_ID_NOT_NULL);
        }

        // 查询目标用户
        Users targetUser = userMapper.selectById(targetUserId);
        if (targetUser == null) {
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        // 获取当前用户ID和角色
        BigInteger currentUserId = UserContext.getCurrentUserId();
        String roleCode = permissionServiceFeignClient.getUserRoleCode(currentUserId);
        if (roleCode.isEmpty()) {
            throw new NoPermissionException(MessageConstant.NO_PERMISSION);
        }

        // 权限判断
        if (UserMessageConstant.USER.equals(roleCode)) {
            // 普通用户只能查自己
            if (!currentUserId.equals(targetUserId)) {
                throw new NoPermissionException(MessageConstant.NO_PERMISSION);
            }
        } else if (UserMessageConstant.ADMIN.equals(roleCode)) {
            // 管理员可以查询自己和普通用户
            if (!currentUserId.equals(targetUserId)) {
                String targetUserRole = permissionServiceFeignClient.getUserRoleCode(targetUserId);
                if (targetUserRole.isEmpty() || !UserMessageConstant.USER.equals(targetUserRole)) {
                    throw new NoPermissionException(MessageConstant.NO_PERMISSION);
                }
            }
        } else if (UserMessageConstant.SUPER_ADMIN.equals(roleCode)) {
            // 超级管理员可查所有用户
        } else {
            throw new NoPermissionException(MessageConstant.NO_PERMISSION);
        }

        // 返回用户信息
        return new UserVO(targetUser.getUserId(), targetUser.getUserName(), targetUser.getEmail(), targetUser.getPhone());
    }

    @Override
    @Transactional
    public void updateById(BigInteger targetUserId, UserDTO users, HttpServletRequest request) {
        // 查询目标用户
        Users oldUser = userMapper.selectById(targetUserId);
        if (oldUser == null) {
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        // 获取当前用户信息
        BigInteger currentUserId = UserContext.getCurrentUserId();
        String roleCode = permissionServiceFeignClient.getUserRoleCode(currentUserId);
        if (roleCode.isEmpty()) {
            throw new NoPermissionException(MessageConstant.NO_PERMISSION);
        }

        // 权限判断
        if (UserMessageConstant.USER.equals(roleCode)) {
            if (!currentUserId.equals(targetUserId)) {
                throw new NoPermissionException(MessageConstant.NO_PERMISSION);
            }
        } else if (UserMessageConstant.ADMIN.equals(roleCode)) {
            if (!currentUserId.equals(targetUserId)) {
                String targetUserRole = permissionServiceFeignClient.getUserRoleCode(targetUserId);
                if (targetUserRole.isEmpty() || !UserMessageConstant.USER.equals(targetUserRole)) {
                    throw new NoPermissionException(MessageConstant.NO_PERMISSION);
                }
            }
        } else if (UserMessageConstant.SUPER_ADMIN.equals(roleCode)) {
            // 超级管理员可以修改所有用户
        } else {
            throw new NoPermissionException(MessageConstant.NO_PERMISSION);
        }

        // 唯一性校验（用户名、邮箱、手机号）
        validateUniqueFields(users, targetUserId);

        // 执行更新
        Users user = new Users();
        BeanUtils.copyProperties(users, user);
        user.setUserId(targetUserId);
        userMapper.updateById(user);

        // 生成操作日志
        Users newUser = userMapper.selectById(targetUserId);
        List<DetailDTO> logDetails = DetailDTO.getDifference(oldUser, newUser);
        String messageId = IdUtil.randomUUID().toString();

        // 如果存在变更，发送日志到 MQ
        if (!logDetails.isEmpty()) {
            String detailJson = JSONUtil.toJsonStr(logDetails);
            logProduct.send(new OperationLogEvent(currentUserId, UserMessageConstant.UPDATE, request.getRemoteAddr(), detailJson, messageId));
            return;
        }

        // 如果没有变更，抛异常
        throw new NoChangeException(MessageConstant.NO_CHANGE);
    }

    /**
     * 唯一性校验（用户名、邮箱、手机号），排除自己
     */
    private void validateUniqueFields(UserDTO users, BigInteger targetUserId) {
        QueryWrapper<Users> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", users.getUserName()).ne("user_id", targetUserId);
        if (userMapper.selectCount(queryWrapper) > 0) {
            throw new UserNameExistException(MessageConstant.USERNAME_EXISTS);
        }

        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", users.getEmail()).ne("user_id", targetUserId);
        if (userMapper.selectCount(queryWrapper) > 0) {
            throw new EmailExistException(MessageConstant.EMAIL_EXISTS);
        }

        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", users.getPhone()).ne("user_id", targetUserId);
        if (userMapper.selectCount(queryWrapper) > 0) {
            throw new PhoneExistException(MessageConstant.PHONE_EXISTS);
        }
    }

    @Override
    public void resetPassword(ResetPasswordDTO reqDTO, HttpServletRequest request) {
        // 参数校验
        if (reqDTO.getUserId() == null || StrUtil.isBlank(reqDTO.getNewPassword())) {
            throw new RuntimeException(MessageConstant.USER_ID_AND_NEW_PASSWORD_NOT_NULL);
        }

        // 获取当前用户信息
        BigInteger currentUserId = UserContext.getCurrentUserId();
        String roleCode = permissionServiceFeignClient.getUserRoleCode(currentUserId);
        if (roleCode.isEmpty()) {
            throw new NoPermissionException(MessageConstant.NO_PERMISSION);
        }

        // 权限判断
        if (UserMessageConstant.USER.equals(roleCode)) {
            if (!currentUserId.equals(reqDTO.getUserId())) {
                throw new NoPermissionException(MessageConstant.NO_PERMISSION);
            }
        } else if (UserMessageConstant.ADMIN.equals(roleCode)) {
            List<BigInteger> userIds = userMapper.selectUserIdsByRoleCode(UserMessageConstant.USER);
            if (CollectionUtil.isEmpty(userIds)) {
                throw new NoRegularUserException(MessageConstant.NO_REGULAR_USER);
            }
            userIds.add(currentUserId);
            if (!userIds.contains(reqDTO.getUserId())) {
                throw new NoPermissionException(MessageConstant.NO_PERMISSION);
            }
        } else if (UserMessageConstant.SUPER_ADMIN.equals(roleCode)) {
            // 超级管理员可以重置所有用户密码
        } else {
            throw new NoPermissionException(MessageConstant.NO_PERMISSION);
        }

        // 执行密码更新
        Users user = new Users();
        user.setUserId(reqDTO.getUserId());
        user.setPassword(reqDTO.getNewPassword());
        userMapper.updateById(user);
    }

    @Override
    @Transactional
    public void deleteById(BigInteger userId, HttpServletRequest request) {
        // 查询目标用户是否存在
        Users user = userMapper.selectById(userId);
        if (user == null) {
            throw new NoUserException(MessageConstant.NO_USER);
        }

        // 获取当前用户角色
        String roleCode = permissionServiceFeignClient.getUserRoleCode(userId);
        if (roleCode.isEmpty()) {
            throw new NoPermissionException(MessageConstant.NO_PERMISSION);
        }

        // 只有超级管理员可以删除用户
        if (!UserMessageConstant.SUPER_ADMIN.equals(roleCode)) {
            throw new NoPermissionException(MessageConstant.NO_PERMISSION);
        }

        // 执行级联删除
        userMapper.deleteById(userId);
        QueryWrapper<UserRoles> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(UserMessageConstant.USER_ID, userId);
        userRolesMapper.delete(queryWrapper);
    }

    @Override
    public Result upgradeToAdmin(BigInteger userId, HttpServletRequest request) {
        // 获取当前用户ID
        BigInteger currentUserId = UserContext.getCurrentUserId();

        // 调用权限服务，提升权限
        Result result = permissionServiceFeignClient.upgradeToAdmin(userId, currentUserId);
        if (result.getCode() == 0 && result.getMsg().equals(MessageConstant.NO_PERMISSION)) {
            return Result.error(MessageConstant.NO_PERMISSION);
        }
        if (result.getCode() == 0 && result.getMsg().equals(MessageConstant.USER_IS_ADMIN)) {
            return Result.error(MessageConstant.USER_IS_ADMIN);
        }
        if (result.getCode() == 0 && result.getMsg().equals(MessageConstant.USER_IS_SUPER_ADMIN)) {
            return Result.error(MessageConstant.USER_IS_SUPER_ADMIN);
        }
        return Result.success(MessageConstant.UP_ADMIN_SUCCESS);
    }

    @Override
    public Result downgradeToUser(BigInteger userId, HttpServletRequest request) {
        // 获取当前用户ID
        BigInteger currentUserId = UserContext.getCurrentUserId();

        // 调用权限服务，降低权限
        Result result = permissionServiceFeignClient.downgradeToUser(userId, currentUserId);
        if (result.getCode() == 0 && result.getMsg().equals(MessageConstant.NO_PERMISSION)) {
            return Result.error(MessageConstant.NO_PERMISSION);
        }
        if (result.getCode() == 0 && result.getMsg().equals(MessageConstant.USER_IS_USER)) {
            return Result.error(MessageConstant.USER_IS_USER);
        }
        if (result.getCode() == 0 && result.getMsg().equals(MessageConstant.USER_IS_SUPER_ADMIN)) {
            return Result.error(MessageConstant.USER_IS_SUPER_ADMIN);
        }

        return Result.success(MessageConstant.DOWN_ADMIN_SUCCESS);
    }
}
